#include <iostream>
#include <string>
using namespace std;
template<typename NameType = string, typename AgeType = int>
class Person
{
public:
	Person()
	{
		cout<<"Person()"<<endl;
	}
	Person(NameType name, AgeType age)
	{
		this->name = name;
		this->age = age;
	}
	void showPerson()
	{
		cout<<this->name<<endl;
		cout<<this->age<<endl;
	}
	~Person(){};
	NameType name;
	AgeType age;
};
template<typename PersonType1, typename PersonType2, typename PersonType3>
class SubPerson: public Person<PersonType1, PersonType2>
{
public:
	SubPerson(PersonType3 name);
	~SubPerson(){};
	PersonType3 name;
};
// class template number without class
template<typename PersonType1, typename PersonType2, typename PersonType3>
SubPerson<PersonType1, PersonType2, PersonType3>::SubPerson(PersonType3 name)
{
	this->name = name;
	cout<<"SubPerson::PersonType3:"<<typeid(PersonType3).name()<<endl;
	cout<<"PersonType3::name:"<<this->name<<endl;
}
template<typename NameType, typename AgeType>
void printPerson(Person<NameType, AgeType> & p)
{
	p.showPerson();
	cout<<"NameType:"<<typeid(NameType).name()<<endl;
	cout<<"AgeType:"<<typeid(AgeType).name()<<endl;
}
template<typename PersonType>
void abstractPerson(PersonType & p)
{
	p.showPerson();
	cout<<"PersonType:"<<typeid(PersonType).name()<<endl;
}
int main(int argc, char const *argv[])
{
	// Person<string, int> p1("haha", 10);
	Person<> p2("hehe", 20);
	SubPerson<string, int, string> ssp("you are paratrooper");
	// printPerson(p1);
	abstractPerson(p2);
	return 0;
}